/*
 * Copyright 2007 Dan Hodge
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.datajanitor.baja.spi.support;

import java.io.File;
import java.util.Map;

import net.datajanitor.baja.spi.Authenticator;
import net.datajanitor.baja.spi.BoxConnectionProvider;
import net.datajanitor.baja.spi.BoxSpiException;
import net.datajanitor.baja.spi.data.AuthInfo;

/**
 * Factory class that can be used to wrap an Authenticator in a caching wrapper
 * that will delegate to a disk-based cache before attempting to authenticate.
 */
public class CachingAuthenticatorFactory {
    private final long timeout;
    private final Map<String, AuthInfo> authInfoMap;
    
    private class CachingAuthenticator implements Authenticator {
        private Authenticator authenticator;
        
        private CachingAuthenticator(Authenticator authenticator) {
            this.authenticator = authenticator;    
        }
        
        public AuthInfo authenticate(BoxConnectionProvider provider) throws BoxSpiException {
            AuthInfo auth = authInfoMap.get(this.authenticator.getKey());  
            if (auth == null || auth.checkTimeout(timeout)) {
                try {
                    auth = this.authenticator.authenticate(provider);
                    authInfoMap.put(this.authenticator.getKey(), auth);
                } catch (BoxSpiException e) {
                    authInfoMap.remove(this.authenticator.getKey());
                    throw e;
                }
            }
            
            return auth;
        }

        public String getKey() {
            return this.authenticator.getKey();
        }
    }
    
    public CachingAuthenticatorFactory() {
        this(15L * 60L * 1000L);
    }
    
    public CachingAuthenticatorFactory(long timeout) {
        File cachedAuth = new File(System.getProperty("user.home") + "/.box");
        this.authInfoMap = new PersistentMap<String, AuthInfo>(cachedAuth);
        this.timeout = timeout;
    }
    
    public Authenticator getCachingAuthenticator(Authenticator authenticator) {
        return new CachingAuthenticator(authenticator);   
    }
}
